package com.jcli.jb51_net.article._198498_实现基于UDP协议网络Socket编程;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.IOException;

/**
 * 【基于UDP协议网络Socket编程(java实现C/S通信案例) 】
 * [https://www.jb51.net/article/198498.htm]
 */
public class UDPClientFX extends Application {

    private Button btnExit = new Button("退出");
    private Button btnSend = new Button("发送");

    private TextField tfSend = new TextField();//输入信息区域

    private TextArea taDisplay = new TextArea();//显示区域
    private TextField ipAddress = new TextField();//填写ip地址
    private TextField tfport = new TextField();//填写端口
    private Button btConn = new Button("连接");
    private UDPClient UDPClient;

    private String ip;
    private String port;


    // 在 UDPClientFX 类中添加一个 TextArea
    private TextArea serverOutputArea = new TextArea();

    @Override
    public void start(Stage primaryStage) {
        // 开启服务器线程
        startUDPServer();

        BorderPane mainPane = new BorderPane();

        //连接服务器区域
        HBox hBox1 = new HBox();
        hBox1.setSpacing(10);
        hBox1.setPadding(new Insets(10, 20, 10, 20));
        hBox1.setAlignment(Pos.CENTER);
        hBox1.getChildren().addAll(new Label("ip地址："), ipAddress, new Label("端口："), tfport, btConn);
        mainPane.setTop(hBox1);


        VBox vBox = new VBox();
        vBox.setSpacing(10);

        vBox.setPadding(new Insets(10, 20, 10, 20));
        vBox.getChildren().addAll(new Label("信息显示区"), taDisplay, new Label("信息输入区"), tfSend);

        VBox.setVgrow(taDisplay, Priority.ALWAYS);
        mainPane.setCenter(vBox);


        HBox hBox = new HBox();
        hBox.setSpacing(10);
        hBox.setPadding(new Insets(10, 20, 10, 20));
        hBox.setAlignment(Pos.CENTER_RIGHT);
        hBox.getChildren().addAll(btnSend, btnExit);
        mainPane.setBottom(hBox);

        Scene scene = new Scene(mainPane, 700, 500);
        primaryStage.setScene(scene);
        primaryStage.show();

        //// TODO: 2023/12/16

        // 在 start 方法中初始化 serverOutputArea
        serverOutputArea.setEditable(false);
        serverOutputArea.setWrapText(true);
        serverOutputArea.setPrefColumnCount(20);

// 将 serverOutputArea 添加到界面左侧
        VBox vBox1 = new VBox();
        vBox1.setSpacing(10);

        vBox1.setPadding(new Insets(10, 20, 10, 20));
        vBox1.getChildren().addAll(new Label("信息显示区"), taDisplay, new Label("信息输入区"), tfSend, new Label("服务器输出"), serverOutputArea);

// 为 serverOutputArea 设置自动滚动
        serverOutputArea.textProperty().addListener((observable, oldValue, newValue) -> {
            serverOutputArea.setScrollTop(Double.MAX_VALUE);
        });

        VBox.setVgrow(taDisplay, Priority.ALWAYS);
        mainPane.setCenter(vBox1);


        //连接服务器之前，发送bye后禁用发送按钮，禁用Enter发送信息输入区域，禁用下载按钮
        btnSend.setDisable(true);
        tfSend.setDisable(true);

        //连接按钮
        btConn.setOnAction(event -> {
            ip = ipAddress.getText().trim();
            port = tfport.getText().trim();

            try {
                UDPClient = new UDPClient(ip, port, serverOutputArea); // 传递 serverOutputArea
                // UDPClient = new UDPClient(ip,port);
                //连接服务器之后未结束服务前禁用再次连接
                btConn.setDisable(true);
                //重新连接服务器时启用输入发送功能
                tfSend.setDisable(false);
                btnSend.setDisable(false);

            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        //发送按钮事件
        btnSend.setOnAction(event -> {
            String msg = tfSend.getText();
            UDPClient.send(msg);//向服务器发送一串字符
            taDisplay.appendText("客户端发送：" + msg + "\n");

            String Rmsg = null;
            Rmsg = UDPClient.receive();
//      System.out.println(Rmsg);
            taDisplay.appendText(Rmsg + "\n");

            if (msg.equals("bye")) {
                btnSend.setDisable(true);//发送bye后禁用发送按钮
                tfSend.setDisable(true);//禁用Enter发送信息输入区域
                //结束服务后再次启用连接按钮
                btConn.setDisable(false);
            }
            tfSend.clear();
        });
        //对输入区域绑定键盘事件
        tfSend.setOnKeyPressed(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                if (event.getCode() == KeyCode.ENTER) {
                    String msg = tfSend.getText();
                    UDPClient.send(msg);//向服务器发送一串字符
                    taDisplay.appendText("客户端发送：" + msg + "\n");


                    String Rmsg = null;
                    Rmsg = UDPClient.receive();
                    taDisplay.appendText(Rmsg + "\n");

                    if (msg.equals("bye")) {
                        tfSend.setDisable(true);//禁用Enter发送信息输入区域
                        btnSend.setDisable(true);//发送bye后禁用发送按钮
                        //结束服务后再次启用连接按钮
                        btConn.setDisable(false);
                    }
                    tfSend.clear();
                }
            }
        });

        btnExit.setOnAction(event -> {
            try {
                exit();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        });
        //窗体关闭响应的事件,点击右上角的×关闭,客户端也关闭
        primaryStage.setOnCloseRequest(event -> {
            try {
                exit();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });


        //信息显示区鼠标拖动高亮文字直接复制到信息输入框，方便选择文件名
        //taDispaly为信息选择区的TextArea，tfSend为信息输入区的TextField
        //为taDisplay的选择范围属性添加监听器，当该属性值变化(选择文字时)，会触发监听器中的代码
        taDisplay.selectionProperty().addListener(((observable, oldValue, newValue) -> {
            //只有当鼠标拖动选中了文字才复制内容
            if (!taDisplay.getSelectedText().equals(""))
                tfSend.setText(taDisplay.getSelectedText());
        }));
    }

    private void startUDPServer() {
        new Thread(() -> {
            try {
                // 创建 UDPServer 实例并运行
                UDPServer udpServer = new UDPServer(null, 8976);
                udpServer.service();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }

    private void exit() throws InterruptedException {
        if (UDPClient != null) {
            //向服务器发送关闭连接的约定信息
            UDPClient.send("bye");
            UDPClient.close();
        }
        System.exit(0);
    }


    public static void main(String[] args) {
        launch(args);
    }
}